package com.company;

// 阻塞队列
public final class MyQueue<T> {
    // 队列数量
    private int count = 0;
    // 最终的数据存储
    private Object[] items;

    // 队列满时的阻塞锁
    private Object full = new Object();
    // 队列空时的阻塞锁
    private Object empty = new Object();

    //写入数据时的下标
    private int putIndex;
    // 获取数据时的下标
    private int getIndex;

    // 初始化
    public MyQueue(int size) {
        items = new Object[size];
    }
    // 获取大小
    public int size() {
        return count;
    }
    /**
     * put方法 从队列尾写入数据
     */
    public void put(T t) {
        // 数据满的情况下
        synchronized (full) {
            while(count==items.length) {
                try {
                    // 满了的情况下等待
                    full.wait();
                }catch (InterruptedException e) {

                    break;
                }
            }
        }
        // 数据空的情况下
        synchronized (empty) {
            // 写入
            items[putIndex++] = t;
            count++;

            // 查看是否到尾巴了
            if(putIndex==items.length) {
                // 超过数组长度后需要从头开始
                putIndex=0;
            }

            // 有数据了唤醒
            empty.notify();
        }
    }

    // 从队列头获取数据
    public T get() {
        // 如果是空的情况
        synchronized (empty) {
            while(count==0) {
                try {
                    empty.wait();
                }catch (InterruptedException e) {
                    // TODO: handle exception
                    return null;
                }
            }
        }

        // 如果是满的情况下
        synchronized (full) {
            Object result = items[getIndex];
            items[getIndex] = null;
            getIndex++;
            count--;

            if(getIndex==items.length) {
                getIndex=0;
            }
            // 唤醒线程
            full.notify();
            return (T)result;
        }
    }

}

